home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
math
/
fixfloa2
/
fixfloat.asm
< prev
next >
Wrap
Assembly Source File
|
1995-03-29
|
34KB
|
1,680 lines
.386
_TEXT SEGMENT BYTE PUBLIC USE32 'CODE'
ASSUME cs:_TEXT
extern _rand_table:dword
extern _sin_table:word
extern _asin_table:word
extern _tan_table1:dword
extern _tan_table3:dword
extern _tan_table4:dword
extern _atan_table1:word
extern _atan_table2:word
extern _atan_table3:word
extern _atan_table4:word
extern _log2_table:word
extern _exp2_table:word
extern _sqrt_table:word
public _rnd1
public _rnd2
public _rnd3
_rnd1 dd 193
_rnd2 dd 0
_rnd3 dd 122231
public rand32_
rand32_ proc near
push edx
mov edx,[_rnd3]
mov eax,[_rnd1]
and edx,03FFh
mul edx
inc [_rnd2]
mov edx,[_rnd2]
and edx,16383
jne r_a
push edx
shr edx,14
add [_rnd3],3
and edx,16383
add eax,[_rand_table+edx]
add [_rand_table+edx],1239876
pop edx
r_a: add eax,[_rand_table+edx]
pop edx
mov [_rnd1],eax
ret
rand32_ endp
; eax - desired two pow interval
; edx - desired interval
public randpowint_
randpowint_ proc near
push ebx
mov ebx,eax
get_another:
; unrolling starts
push edx
mov edx,[_rnd3]
mov eax,[_rnd1]
and edx,03FFh
mul edx
inc [_rnd2]
mov edx,[_rnd2]
and edx,16383
jne pir_a
push edx
shr edx,14
add [_rnd3],3
and edx,16383
add eax,[_rand_table+edx]
add [_rand_table+edx],1239876
pop edx
pir_a: add eax,[_rand_table+edx]
pop edx
mov [_rnd1],eax
; unrolling stops
and eax,ebx
cmp eax,edx
jae get_another
pop ebx
ret
randpowint_ endp
public randinter_
randinter_ proc near
push edx
push ecx
push eax
frl00: xor ecx,ecx
cmp eax,010000h
jb frl0
shr eax,16
add cl,16
frl0: cmp eax,0100h
jb frl1
shr eax,8
add cl,8
frl1: cmp eax,010h
jb frl2
shr eax,4
add cl,4
frl2: cmp eax,04h
jb frl3
shr eax,2
add cl,2
frl3: cmp eax,2
jb frl4
inc ecx
frl4: inc cl
mov edx,1
shl edx,cl
pop ecx
dec edx ; eax now holding 2pow interval
gget_another:
; unrolling starts
push edx
mov edx,[_rnd3]
mov eax,[_rnd1]
and edx,03FFh
mul edx
inc [_rnd2]
mov edx,[_rnd2]
and edx,16383
jne ir_a
push edx
shr edx,14
add [_rnd3],3
and edx,16383
add eax,[_rand_table+edx]
add [_rand_table+edx],1239876
pop edx
ir_a: add eax,[_rand_table+edx]
pop edx
mov [_rnd1],eax
; unrolling stops
and eax,edx
cmp eax,ecx
jae gget_another
pop ecx
pop edx
ret
randinter_ endp
public ffsmul_
; eax - contains fixfloat 1
; edx - contains fixfloat 2
; routine affects edx due to 64 bit multiplication
ffsmul_ proc near
imul edx
shrd eax,edx,16
ret
ffsmul_ endp
public ffsdiv_
; eax contains denominator (Above division line)
; edx contains nominator (Below division line)
ffsdiv_ proc near
push edx
push ecx
push ebx
or eax,eax
mov ecx,edx
mov bl,0
jns fsd_1
neg eax
inc bl
fsd_1: or ecx,ecx
mov edx,eax
jns fsd_2
neg ecx
inc bl
fsd_2: shr edx,16
shl eax,16
cmp edx,ecx
jae div_by_0
div ecx
test bl,1
pop ebx
pop ecx
pop edx
je fsd_3
neg eax
fsd_3: ret
div_by_0: test bl,1
pop ebx
pop ecx
pop edx
jne dbz1
mov eax,07FFFFFFFh
ret
dbz1: mov eax,080000000h
ret
ffsdiv_ endp
public ffmul_
; eax - contains fixfloat 1
; edx - contains fixfloat 2
; routine affects edx due to 64 bit multiplication
ffmul_ proc near
mul edx
shrd eax,edx,16
ret
ffmul_ endp
public ffdiv_
; eax contains denominator (Above division line)
; edx contains nominator (Below division line)
ffdiv_ proc near
push edx
push ecx
mov ecx,edx
mov edx,eax
shl eax,16
shr edx,16
cmp edx,ecx
jae div_by_00
div ecx
pop ecx
pop edx
ret
div_by_00:
pop ecx
pop edx
mov eax,0FFFFFFFFh
ret
ffdiv_ endp
public ffsin_
public ffcos_
ffcos_:
add eax,04000h ; that's all there is to it !
ffsin_ proc near
push ebx
test eax,08000h
setne bl
and eax,07FFFh
cmp eax,04000h
jb fsn1
xor eax,07FFFh
fsn1: shr eax,2 ; increased resolution 4 times
mov ax,[_sin_table+eax*2]
or bl,bl
je ffsn2
neg eax
ffsn2: pop ebx
ret
ffsin_ endp
public ffasin_
ffasin_ proc near
push ebx
or eax,eax
mov bl,0
jns fasn2
neg eax
inc ebx
fasn2: and eax,0FFFFh
shr eax,4
mov ax,[_asin_table+eax*2]
or bl,bl
je fasn1
neg eax
fasn1: pop ebx
ret
ffasin_ endp
public ffacos_
ffacos_ proc near
push ebx
or eax,eax
mov bl,0
jns facn2
neg eax
inc ebx
facn2: and eax,0FFFFh
shr eax,4
mov ax,[_asin_table+eax*2]
or bl,bl
je facn1
neg eax
facn1: pop ebx
sub eax,04000h
neg eax
ret
ffacos_ endp
public fftan_
fftan_ proc near
push ebx
test eax,4000h
mov bl,0
je ftn1
test eax,3FFFh
jne ftn01
mov eax,030000000h ; almost infinity
pop ebx
ret
ftn01: neg eax
inc bl
ftn1: and eax,03FFFh
cmp eax,03C00h
jae ftn3
shr eax,4 ; lowest tan interval
or bl,bl
mov eax,[_tan_table1+eax*4]
je ftn11
neg eax
ftn11: pop ebx
ret
ftn3: cmp eax,03F00h
jae ftn4
and eax,03fch
or bl,bl
mov eax,[_tan_table3+eax]
je ftn31
neg eax
ftn31: pop ebx
ret
ftn4: and eax,0FFh
or bl,bl
mov eax,[_tan_table4+eax*4]
je ftn41
neg eax
ftn41: pop ebx
ret
fftan_ endp
public ffatan_
ffatan_ proc near
push ebx
or eax,eax
mov bl,0
jns fat0
neg eax
inc ebx
fat0: cmp eax,040000h
jae fat1
shr eax,8
or bl,bl
mov ax,[_atan_table1+eax*2]
je fat01
neg eax
fat01: pop ebx
ret
fat1: cmp eax,0100000h
jae fat2
shr eax,12
or bl,bl
mov ax,[_atan_table2+eax*2]
je fat11
neg eax
fat11: pop ebx
ret
fat2: cmp eax,02000000h ; 512.0
jae fat3
shr eax,17
or bl,bl
mov ax,[_atan_table3+eax*2]
je fat21
neg eax
fat21: pop ebx
ret
fat3: cmp eax,020000000h ; 8192.0
jae fat4
shr eax,21
or bl,bl
mov ax,[_atan_table4+eax*2]
je fat31
neg eax
fat31: pop ebx
ret
fat4: or bl,bl
mov eax,03FFFh ; almost 90 degrees
jns fat31
neg eax
jmp fat31
ffatan_ endp
public fflog2_
fflog2_ proc near
push ecx
push ebx
or eax,eax
mov ebx,eax
jne ffl00
mov eax,80000000h ; approx -infinity
pop ebx
pop ecx
ret
ffl00: xor ecx,ecx
cmp eax,010000h
jb ffl0
shr eax,16
add cl,16
ffl0: cmp eax,0100h
jb ffl1
shr eax,8
add cl,8
ffl1: cmp eax,010h
jb ffl2
shr eax,4
add cl,4
ffl2: cmp eax,04h
jb ffl3
shr eax,2
add cl,2
ffl3: cmp eax,2
jb ffl4
inc ecx
ffl4: mov eax,ebx
mov bl,cl
sub cl,12
js ffl5
shr eax,cl
jmp ffl6
ffl5: neg cl
shl eax,cl
ffl6: sub eax,01000h
sub bl,16
mov cx,[_log2_table+eax*2]
movsx eax,bl
pop ebx
shl eax,16
mov ax,cx
pop ecx
ret
fflog2_ endp
public ffexp2_
ffexp2_ proc near
; test eax,0FFFFh
push ecx
mov ecx,eax
; je fenodec
shr eax,4
sar ecx,16
js fe1
and eax,0FFFh
mov ax,[_exp2_table+eax*2]
add eax,10000h
shl eax,cl
pop ecx
ret
fe1: and eax,0FFFh
neg cl
mov ax,[_exp2_table+eax*2]
add eax,10000h
shr eax,cl
pop ecx
ret
fenodec: sar ecx,16
mov eax,1
add ecx,16
shl eax,cl
pop ecx
ret
ffexp2_ endp
public ffpow_
ffpow_ proc near ; neat procedure eh?
call fflog2_
call ffsmul_
call ffexp2_
ret
ffpow_ endp
public ffsqrt_
ffsqrt_ proc near
push ecx
push ebx
or eax,eax
mov ebx,eax
jne ffs00
mov eax,0h ; sqrt 0 = 0
pop ebx
pop ecx
ret
ffs00: xor ecx,ecx
cmp eax,010000h
jb ffs0
shr eax,16
add cl,16
ffs0: cmp eax,0100h
jb ffs1
shr eax,8
add cl,8
ffs1: cmp eax,010h
jb ffs2
shr eax,4
add cl,4
ffs2: cmp eax,04h
jb ffs3
shr eax,2
add cl,2
ffs3: cmp eax,2
jb ffs4
inc ecx
ffs4: mov eax,ebx
sub cl,15
test cl,1
je ffs5
inc cl
ffs5: mov bl,cl
add cl,4
jns ffs6
neg cl
shl eax,cl
jmp ffs7
ffs6: shr eax,cl
ffs7: sar bl,1
mov ax,[_sqrt_table+eax*2]
or bl,bl
mov cl,bl
js ffs8
shl eax,cl
pop ebx
pop ecx
ret
ffs8: neg cl
pop ebx
shr eax,cl
pop ecx
ret
ffsqrt_ endp
public fftrihyp_
fftrihyp_ proc near
push ecx
push ebx
fthp0: mov ebx,edx ; 2
imul eax ; edx:eax - a
mov ecx,edx
fthp1: xchg eax,ebx ; ecx:ebx - a
imul eax
add ebx,eax ; 2 2
pop eax
adc ecx,edx ; edx:eax - a +b
push eax
fthp11: imul eax
add eax,ebx
adc edx,ecx
je t_hi_reg_zero
; bsr ecx,edx
; code from here
push edx
xor ecx,ecx
cmp edx,010000h
jb bsr00
shr edx,16
add cl,16
bsr00: cmp edx,0100h
jb bsr01
shr edx,8
add cl,8
bsr01: cmp edx,010h
jb bsr02
shr edx,4
add cl,4
bsr02: cmp edx,04h
jb bsr03
shr edx,2
add cl,2
bsr03: cmp edx,2
jb bsr04
inc ecx
bsr04: pop edx
; to here replaces bsr with a factor 2.5 speed gain
add cl,17
test cl,1
je fthp2
inc ecx
fthp2: mov ebx,ecx
cmp cl,020h
jae fthp20
shrd eax,edx,cl
jmp t_ready_to_root
fthp20: sub cl,020h
mov eax,edx ; 20 shifts
shr eax,cl
jmp t_ready_to_root
t_hi_reg_zero:
; bsr ecx,eax
; code from here
push eax
xor ecx,ecx
cmp eax,010000h
jb bsr10
shr eax,16
add cl,16
bsr10: cmp eax,0100h
jb bsr11
shr eax,8
add cl,8
bsr11: cmp eax,010h
jb bsr12
shr eax,4
add cl,4
bsr12: cmp eax,04h
jb bsr13
shr eax,2
add cl,2
bsr13: cmp eax,2
jb bsr14
inc ecx
bsr14: pop eax
; to here replaces bsr with a factor 2.5 speed gain
sub cl,15
test cl,1
je thrz1
inc ecx
thrz1: mov ebx,ecx
or ecx,ecx
js thrz2
shr eax,cl
jmp t_ready_to_root
thrz2: neg ecx
shl eax,cl
t_ready_to_root:
shr eax,4 ;
mov ecx,ebx
and eax,0fffh
sub cl,16
mov ax,[_sqrt_table+eax*2]
sar cl,1
js trtr1
shl eax,cl
pop ebx
pop ecx
ret
trtr1: neg cl
shr eax,cl
pop ebx
pop ecx
ret
fftrihyp_ endp
public ffhyp_
ffhyp_ proc near
push ecx
push ebx
fhp0: mov ebx,edx ; 2
imul eax ; edx:eax - a
mov ecx,edx
; 2
fhp1: xchg eax,ebx ; ecx:ebx - a
imul eax
add eax,ebx ; 2 2
adc edx,ecx ; edx:eax - a + b
je hi_reg_zero
; bsr ecx,edx
; code from here
push edx
xor ecx,ecx
cmp edx,010000h
jb bsr20
shr edx,16
add cl,16
bsr20: cmp edx,0100h
jb bsr21
shr edx,8
add cl,8
bsr21: cmp edx,010h
jb bsr22
shr edx,4
add cl,4
bsr22: cmp edx,04h
jb bsr23
shr edx,2
add cl,2
bsr23: cmp edx,2
jb bsr24
inc ecx
bsr24: pop edx
; to here replaces bsr with a factor 2.5 speed gain
add cl,17
test cl,1
je fhp2
inc ecx
fhp2: mov ebx,ecx
cmp cl,020h
jae fhp20
shrd eax,edx,cl
jmp ready_to_root
fhp20: sub cl,020h
mov eax,edx ; 020h shifts
shr eax,cl
jmp ready_to_root
hi_reg_zero:
; bsr ecx,eax
; code from here
push eax
xor ecx,ecx
cmp eax,010000h
jb bsr30
shr eax,16
add cl,16
bsr30: cmp eax,0100h
jb bsr31
shr eax,8
add cl,8
bsr31: cmp eax,010h
jb bsr32
shr eax,4
add cl,4
bsr32: cmp eax,04h
jb bsr33
shr eax,2
add cl,2
bsr33: cmp eax,2
jb bsr34
inc ecx
bsr34: pop eax
; to here replaces bsr with a factor 2.5 speed gain
sub cl,15
test cl,1
je hrz1
inc ecx
hrz1: mov ebx,ecx
or ecx,ecx
js hrz2
shr eax,cl
jmp ready_to_root
hrz2: neg ecx
shl eax,cl
ready_to_root:
shr eax,4 ;
mov ecx,ebx
and eax,0fffh
sub cl,16
mov ax,[_sqrt_table+eax*2]
sar cl,1
js rtr1
shl eax,cl
pop ebx
pop ecx
ret
rtr1: neg cl
shr eax,cl
pop ebx
pop ecx
ret
ffhyp_ endp
public ffalmosthyp_
ffalmosthyp_ proc near
or eax,eax
push edx
jns fah_1
neg eax
fah_1: or edx,edx
jns fah_2
neg edx
fah_2: cmp eax,edx
jae fah_3
xchg eax,edx
fah_3: shr edx,1
add eax,edx
pop edx
ret
ffalmosthyp_ endp
public ffmuldiv_
ffmuldiv_ proc near
push esi
push ebx
push ecx
push eax
push edx
ffmd5: mov eax,ebx
imul ecx
je ffmd_zero_nominator
mov ebx,eax
mov ecx,edx
mov eax,[esp]
mov edx,[esp+4]
imul edx
or edx,edx
mov esi,edx ; sign of nominator
jns ffmd51
neg eax ; negating denominator
neg edx
ffmd51: or ecx,ecx
jns ffmd52
xor esi,0x80000000 ; change sign of result
not ebx
not ecx
ffmd52: cmp edx,0xFFFF
ja ffmd520
shld edx,eax,16
shl eax,16
or ecx,ecx
jmp ffmd521
ffmd520: shrd ebx,ecx,16
shr ecx,16
ffmd521: jne ffmd_more_shift
cmp edx,ebx
jae ffmd_overflow
idiv ebx ; there is no test for overflow
or esi,esi
pop edx ; in this division
jns ffmd53
neg eax
ffmd53: add esp,4
pop ecx
pop ebx
pop esi
ret
ffmd_more_shift:
shrd eax,edx,16
shr edx,16
shrd ebx,ecx,16
cmp edx,ebx
jae ffmd_overflow
idiv ebx
or esi,esi
pop edx
jns ffmd54
neg eax
ffmd54: add esp,4
pop ecx
pop ebx
pop esi
ret
ffmd_overflow:
pop edx
add esp,4
or esi,esi
js ffmd6
mov eax,07FFFFFFFh
pop ecx
pop ebx
pop esi
ret
ffmd_zero_nominator:
pop edx
pop eax
xor eax,edx
js ffmd6
mov eax,07FFFFFFFh ; positive infinity
pop ecx
pop ebx
pop esi
ret
ffmd6: mov eax,080000000h ; negative infinity
pop ecx
pop ebx
pop esi
ret
ffmuldiv_ endp
public ffmmd_
ffmmd_ proc near
push esi
push ebx
xor esi,esi
push edx
ffmmd2: imul edx
jns ffmmd3
neg edx
neg eax
inc esi
ffmmd3: or ebx,ebx
jns ffmmd4
neg ebx
dec esi
ffmmd4: cmp edx,ebx
jae ffmmd_overflow
div ebx
or esi,esi
pop edx
je ffmmd5
neg eax
ffmmd5: pop ebx
pop esi
ret
ffmmd_overflow:
or esi,esi
pop edx
pop ebx
pop esi
js ffmmd6
mov eax,07FFFFFFFh
ret
ffmmd6: mov eax,080000000h
ret
ffmmd_ endp
public ffortproj_
; eax - a
; edx - b
; ebx - c
; ecx - d
; returns (a*b+c*d)/(a*a+c*c)
ffortproj_ proc near
push ebx
push edx
push ecx
sar eax,5
sar edx,5
sar ebx,5
sar ecx,5
push eax
call ffsmul_ ; eax = a*b
push eax
mov eax,ebx
mov edx,ecx
call ffsmul_ ; eax = c*d
pop ecx ; ecx = a*b
add ecx,eax ; ecx = a*b + c*d
mov eax,ebx
mov edx,ebx
call ffsmul_
mov ebx,eax ; ebx = c*c
pop eax
mov edx,eax
call ffsmul_ ; eax = a*a
add ebx,eax ; ebx = c*c + a*a
mov eax,ecx
mov edx,ebx
call ffsdiv_
pop ecx
pop edx
pop ebx
ret
ffortproj_ endp
public ffortproj1_
; eax - a
; edx - b
; ebx - c
; ecx - d
; returns (a*b+c*d)/sqrt(a*a+c*c)
ffortproj1_ proc near
push ebx
push edx
push ecx
sar eax,6
sar edx,6
sar ebx,6
sar ecx,6
push eax
call ffsmul_ ; eax = a*b
push eax
mov eax,ebx
mov edx,ecx
call ffsmul_ ; eax = c*d
pop ecx ; ecx = a*b
add ecx,eax ; ecx = a*b + c*d
mov eax,ebx
mov edx,ebx
call ffsmul_
mov ebx,eax ; ebx = c*c
pop eax
mov edx,eax
call ffsmul_ ; eax = a*a
add eax,ebx ; ebx = c*c + a*a
call ffsqrt_ ; root it
mov edx,eax
mov eax,ecx
call ffsdiv_
shl eax,6 ; compensating root
pop ecx
pop edx
pop ebx
ret
ffortproj1_ endp
public ffdot_through_hyps_
; eax - a
; edx - b
; ebx - c
; ecx - d
; returns (a*b+c*d)/(sqrt(a*a+c*c)*sqrt(b*b+d*d))
ffdot_through_hyps_ proc near
push ebx
push edx
push ecx
sar eax,5
sar edx,5
sar ebx,5
sar ecx,5
push edx
push ecx
push eax
call ffsmul_ ; eax = a*b
push eax
mov eax,ebx
mov edx,ecx
call ffsmul_ ; eax = c*d
pop ecx ; ecx = a*b
add ecx,eax ; ecx = a*b + c*d
mov eax,ebx
mov edx,ebx
call ffsmul_
mov ebx,eax ; ebx = c*c
pop eax
mov edx,eax
call ffsmul_ ; eax = a*a
add eax,ebx
call ffsqrt_
mov ebx,eax ; ebx = sqrt(c*c + a*a)
pop eax
mov edx,eax
call ffsmul_ ; eax = d*d
pop edx
push eax
mov eax,edx
call ffsmul_ ; eax = b*b
pop edx
add eax,edx
call ffsqrt_ ; eax = sqrt(d*d + b*b)
mov edx,ebx
call ffmul_ ; eax = sqrt(d*d + b*b) * sqrt(c*c + a*a)
mov edx,eax
mov eax,ecx
call ffsdiv_ ; eax = a*b + c*d / (sqrt(d*d + b*b) * sqrt(c*c + a*a))
pop ecx
pop edx
pop ebx
ret
ffdot_through_hyps_ endp
public isqrt_
isqrt_ proc near
push ecx
push edx
push eax
; bsr ecx,eax ; unfold
; code from here
xor ecx,ecx
cmp eax,010000h
jb is30
shr eax,16
add cl,16
is30: cmp eax,0100h
jb is31
shr eax,8
add cl,8
is31: cmp eax,010h
jb is32
shr eax,4
add cl,4
is32: cmp eax,04h
jb is33
shr eax,2
add cl,2
is33: cmp eax,2
jb is34
inc ecx
is34:
; to here replaces bsr with a factor 2.5 speed gain
mov edx,ecx
sub cl,10
neg edx
test cl,1
pop eax
je is1
inc edx
dec ecx
is1:
add dl,31
or cl,cl
js is2
shr eax,cl
jmp is3
is2:
neg cl
shl eax,cl
is3:
shr dl,1
mov ax,[_sqrt_table+eax*2]
mov ecx,edx
pop edx
shr eax,cl
pop ecx
ret
isqrt_ endp
; eax - denominator lo part
; edx - denominator hi
; ebx - nominator
; ecx - pointer to DWORD location to store
; decimal fraction of result.
; returns the integer part of result
; works with signed 64 bit quantities
; this routine does not check for any zero divisions
public ff_double_div_
ff_double_div_ proc near
push edx
push edi
xor edi,edi
or edx,edx
jns dd_1
neg edx
neg eax ; make both numbers positive
sbb edx,0
inc edi
dd_1: or ebx,ebx
jns dd_2
neg ebx
inc edi
dd_2: div ebx
push eax ; this is integer part of
; division
xor eax,eax ; produce decimal part of
div ebx ; division
pop edx ; eax - decpart, edx - intpart
dd_4: test edi,1
je dd_5
neg edx ; negate integer part
neg eax ; negate decimal part
sbb edx,0 ; dec if non zero eax
dd_5: mov [ecx],eax ; store away decimal fraction
mov eax,edx ; return integer fraction
dd_restore_reg:
pop edi ; restore registers
pop edx
ret
ff_double_div_ endp
;
; eax - pointer to low value
; edx - pointer to hi value
; ebx - 0 - ordinary shift
; no 0 - arithmetic shift
; ecx - nr of steps to shift,
; right is positive,
; left is negative
;
public ff_double_shift_
ff_double_shift_ proc near
push esi
or ecx,ecx
js dr_left
; rotate right
mov esi,[edx]
shrd [eax],esi,cl
xor esi,esi
or ebx,ebx
jne dr_aritm
shrd [edx],esi,cl
pop esi
ret
dr_aritm: mov esi,[edx]
sar esi,31
shrd [edx],esi,cl
pop esi
ret
; shift left
dr_left: push ecx
neg ecx
mov esi,[eax]
shld [edx],esi,cl
xor esi,esi
shld [eax],esi,cl
pop ecx
pop esi
ret
ff_double_shift_ endp
; /\ Y
; |
; This routine takes a | o (1,2)
; vector in it's rectangular form | /
; and returns the angle it forms | /\ V = atan(2/1)
; in relation to the point (1,0). |/ |
; that is coordinate (0,1) will return -------------> X
; (90/360)*65536 ,
; coordinate (0,-1) will return
; ((-90/360)*65536) & 65535
;
; renember, there are 65536 degrees in
; a circle in fixfloat universe.
; eax - x component
; edx - y component
; returns result in eax
public ff_vec_to_ang_
ff_vec_to_ang_ proc near
or eax,eax
push edx
push ecx
mov cl,0
js ff_fta0
jne ff_fta1
or edx,edx
je ff_zero_vector
jmp ff_fta1
ff_fta0:
neg eax ; make sure x component is positive
neg edx
inc cl ; flag that we have to subtract/add '180' degrees to angle
ff_fta1:
cmp edx,eax ; test if y>x
jge ff_y_bigger
push edx
neg edx
cmp edx,eax ; test if -y>x
pop edx
jge ff_y_bigger
; abs(x)>abs(y)
xchg eax,edx ; put y on top in divisor, x in bottom
call ffsdiv_ ; divide
call ffatan_ ; arc tan
jmp ff_fta2
ff_y_bigger: ; abs(y)>abs(x)
push 0004000h
or edx,edx
jns ff_yb1
mov DWORD PTR[esp],000c000h
ff_yb1: call ffsdiv_
call ffatan_
neg eax
pop edx
add eax,edx
ff_fta2:
or cl,cl ; see if need to flip angle '180' degrees
pop ecx
je ff_fta3
xor eax,08000h ; flip it
ff_fta3:
and eax,0FFFFh
pop edx
ret
ff_zero_vector:
xor eax,eax
pop ecx
pop edx
ret
ff_vec_to_ang_ endp
;
; this routine solves a 2:nd degree equation
; by std formula, for given p & 1 :
;
; 2
; x + px + q = 0
;
; setup at call :
; eax - p
; edx - q
; ebx - pointer to where to put conjugate part ( the +/- term )
; ecx - pointer to where to put prefix part (-p/2)
;
; returns eax - 0 if solved OK
; returns eax - no 0 if no real roots
;
; routine handles cases where p*p/4-q>32767 correctly,
; since it uses intermediate 64 bit representation
;
public ff_solve_2nd_poly_
ff_solve_2nd_poly_ proc near
push edx
push ecx
push eax
mov ecx,edx ; square the p term
mov edx,eax
imul edx
shrd eax,edx,18 ; work with 64 bits for a while
sar edx,18
or ecx,ecx ; slightly different behaviour if negative q value
js ff2nd_1
sub eax,ecx
sbb edx,0
jmp ff2nd_2
ff2nd_1:
neg ecx
add eax,ecx
adc edx,0
ff2nd_2:
js ff2nd_no_real_roots ; such things happens...
xor ecx,ecx
or edx,edx
je ff2nd_4
ff2nd_3:
shrd eax,edx,2 ; enable momentary overflow but still give correct result
inc ecx ; with the help of afew shifts
shr edx,2
jne ff2nd_3
ff2nd_4:
call ffsqrt_
shl eax,cl
mov [ebx],eax ; storing conjugate
pop eax
pop ecx
neg eax ; calc -p/2
pop edx
sar eax,1
mov [ecx],eax
xor eax,eax ; indicate we did OK
ret
ff2nd_no_real_roots:
pop eax
pop ecx
neg eax
pop edx
sar eax,1
mov [ecx],eax
mov al,1 ; indicate no real roots
ret
ff_solve_2nd_poly_ endp
_TEXT ENDS
END